/*
 * @(#)ChatChannel.java
 *
 * Copyright (c) 1998-2005 Jang-Ho Hwang, 
 * All Rights Reserved.
 *
 * $Id: ChatChannel.java,v 1.1.1.1 2005/05/22 01:02:27 rath Exp $
 */
package rath.nateon;

import java.io.*;
import java.net.URLDecoder;
import java.util.*;
/**
 * 네이트온 메신져 클래스
 * 
 * @author Jang-Ho Hwang, rath@xrath.com
 * @version 1.0.000, 2005/05/20
 */
public class ChatChannel extends NateOnChannel
{	
	public static final String DEFAULT_FONT = "굴림체";

	private final NateOnMessenger nateon;

	private ArrayList friends = new ArrayList();
	private String sessionId; 

	public ChatChannel( NateOnMessenger nateon, String host, int port )
	{
		super( host, port );

		this.nateon = nateon;
	}

	public void setSessionId( String sid )
	{
		this.sessionId = sid;
	}

	public String getSessionId()
	{
		return this.sessionId;
	}

	protected void channelConnected() throws IOException
	{
		NateUser me = nateon.getOwner();

		NateOnMessage out = new NateOnMessage("ENTR");
		out.add( nateon.getUserId() );
		out.add( me.getName() );
		out.add( me.getNickname() );
		out.add( sessionId );
		out.setCallback( "processEnter" );

		writeMessage( out );
	}

	public void processEnter( NateOnMessage msg ) throws IOException
	{
		nateon.fireChannelOpened(this);
	}

	protected void channelClosed()
	{
		nateon.fireChannelClosed(this);

		nateon.notification.removeChatChannel(sessionId);
	}

	/**
	 * 채널을 종료한다.
	 */
	public void close()
	{
		cancel();
	}

	/**
	 * 채널을 취소한다 (종료하고 나간다).
	 */
	public void cancel()
	{
		cleanUp();
	}

	protected void processMessage( NateOnMessage msg ) throws IOException
	{
		String head = msg.getHeader();

		if( head.equals("MESG") )
		{
			processChat( msg );
		}
		else
		if( head.equals("USER") )
		{
			processUser( msg );
		}
		else
		if( head.equals("JOIN") )
		{
			processJoin( msg );
		}
		else
		if( head.equals("QUIT") )
		{
			processQuit( msg );
		}
	}

	protected void processChat( NateOnMessage msg ) throws IOException
	{
		if( msg.size()==0 )
		{
			// ACK 메시지이다.
			return;
		}

		String from = msg.get(0);
		String type = msg.get(1);

		if( type.equals("MSG") )
		{
			String incoming = msg.get(2);
			String[] msgset = incoming.split("%09");

			String font = null;
			String chat = incoming;
			if( msgset.length==4 )
			{
				font = msgset[0];
				chat = msgset[3];
			}
			chat = URLDecoder.decode(chat, "UTF-8");
			nateon.fireChannelMessage( this, from, font, chat );
		}
	}

	protected void processUser( NateOnMessage msg ) throws IOException
	{
		int cur = msg.getInt(0);
		int max = msg.getInt(1);

		String email = msg.get(2);
		String nick = msg.get(3);
		String name = msg.get(4);

		NateUser user = new NateUser();
		user.setEmail( email );
		user.setNickname( nick );
		user.setName( name );

		// 어떻게 할까나
		friends.add( user );
	}

	protected void processJoin( NateOnMessage msg ) throws IOException
	{
		String email = msg.get(0);
		String nick = msg.get(1);
		String name = msg.get(2);

		NateUser user = new NateUser();
		user.setEmail( email );
		user.setNickname( nick );
		user.setName( name );

		friends.add( user );

		nateon.fireChannelJoined( this, user );
	}

	/**
	 * 방에서 누군가가 나갔을때 발생된다.
	 * 마지막 남은자가 방에서 나갔을때는 ChatChannel을 종료하게 된다.
	 */
	protected void processQuit( NateOnMessage msg ) throws IOException
	{
		String email = msg.get(0);

		NateUser toFind = new NateUser();
		toFind.setEmail(email);
		int i0 = friends.indexOf(toFind);
		if( i0==-1 )
			return;

		NateUser parter = (NateUser)friends.remove(i0);
		nateon.fireChannelParted( this, parter );

		if( friends.size()==0 )
		{
			isLive = false;
		}
	}

	public List getUsers()
	{
		return this.friends;
	}

	public void sendMessage( String msg ) throws IOException
	{
		sendMessage( DEFAULT_FONT, msg );
	}

	public void sendMessage( String font, String msg ) throws IOException
	{
		sendMessage( font, "0", "", msg );
	}

	public void sendMessage( String font, String unknown, String style, String msg ) 
		throws IOException
	{
		NateOnMessage out = new NateOnMessage("MESG");
		out.add( "MSG" );
		
		StringBuffer sb = new StringBuffer();
		sb.append( font );
		sb.append( "%09" );
		sb.append( unknown );
		sb.append( "%09" );
		sb.append( style );
		sb.append( "%09" );
		msg = msg.replaceAll("%", "%25");
		msg = msg.replaceAll(" ", "%20");
		msg = msg.replaceAll("\r", "%0D");
		msg = msg.replaceAll("\n", "%0A");
		msg = msg.replaceAll("\t", "%09");
		sb.append( msg );

		out.add( sb.toString() );

		writeMessage( out );
	}

	protected void connectFailed( Exception e )
	{
		e.printStackTrace();
	}
}
